<?php

class Rapide_Cache_Driver_File implements Rapide_Cache_Driver_Interface
{
	private $_oConfig;

	private $_sPath,
					$_sGroupPath,
					$_sFilePath,
					$_sPrefix,
					$_sPostfix,
					$_bHashName,
					$_bHashGroupName,
					$_sGroup,
					$_iLifeTime,
					$_sExtension,
					$_sCacheName,
					$_sFileName;

	public function __construct($sCacheName, $sGroupName, $iLifeTime)
	{

		$this->_oConfig = new Rapide_Config;
		$this->_oConfig->load('Cache/File.php');

		$this->_sGroup		= $sGroupName;
		$this->_iLifeTime	= $iLifeTime;
		$this->_sCacheName	= $sCacheName;
		$this->_sPath		= $this->_oConfig->get('Cache', 'File', 'path');
		$this->_sGroupPath	= $this->_sPath;
		$this->_sPrefix		= $this->_oConfig->get('Cache', 'File', 'prefix');
		$this->_sPostfix	= $this->_oConfig->get('Cache', 'File', 'postfix');
		$this->_sExtension	= $this->_oConfig->get('Cache', 'File', 'extension');
		$this->_sFileName	= $this->prepareFileName($sCacheName);

		$this->preparePaths();
	}

	public function save($mData)
	{

		if(!is_readable($this->_sPath))
			throw new Rapide_Cache_Exception('Directory ' . $this->_sPath . ' is not readable.');

		if(!is_null($this->_sGroup))
		{
			if(!is_dir($this->_sGroupPath))
			{
				if(!mkdir($this->_sGroupPath))
				{
					throw new Rapide_Cache_Exception('Cannot create directory ' . $this->_sGroupPath);
				}
			}
		}

		if(!file_put_contents($this->_sFilePath, $mData))
		{
		 throw new Rapide_Cache_Exception('Caching "' . $this->_sFilePath . '" failed. Make sure, that cache directory is writable.');
		}

	}

	public function load()
	{
		if(!$this->checkIfNotExpired())
		{
			return false;
		}
		else
		{
			return file_get_contents($this->_sFilePath);
		}
	}

	private function prepareFileName($sFileName)
	{
		return $this->_sPrefix . $sFileName . $this->_sPostfix . '.' . $this->_sExtension;
	}

	private function preparePaths()
	{
		$this->_sGroupPath = $this->_sPath . $this->_sGroup .'/';

		if(!is_null($this->_sGroup))
		{
			$this->_sFilePath = $this->_sGroupPath . '/' . $this->_sFileName;
		}
		else
		{
			$this->_sFilePath = $this->_sPath . '/' . $this->_sFileName;
		}

	}

	public function checkIfNotExpired()
	{

		if(!$this->ping())
		{
			return false;
		}

		if((time() - @filemtime($this->_sFilePath) > $this->_iLifeTime))
		{
			return false;
		}
		else
		{
			return true;
		}

	}

	public function ping()
	{
		return(is_readable($this->_sFilePath));
	}

	public function clearAll()
	{
		$this->recursiveDelete($this->_sPath);
	}

	public function clearGroup($sGroupName)
	{
		$this->recursiveDelete($this->_sPath . $sGroupName);
	}

	public function clearOld()
	{
		$this->recursiveDelete($this->_sPath, true);
	}

	public function clearOldFromGroup($sGroupName)
	{
		$this->recursiveDelete($this->_sPath . $sGroupName, true);
	}

	public function remove()
	{
		if(!unlink($this->_sFilePath))
			throw new Rapide_Cache_Exception('Cannot delete ' . $this->_sFilePath);
	}

	private function recursiveDelete($sPath, $bOnlyOld = false)
	{
		if (!is_dir(realpath($sPath)))
			throw new Rapide_Cache_Exception($sPath . ' is not a directory');

		$sDirToScan = array(realpath($sPath));

		$aDirArray = array();

		while (!empty($sDirToScan))
		{
			$sCurrentDir = array_pop($sDirToScan);
			$aDirArray[] = $sCurrentDir;

			if ($rDir = opendir($sCurrentDir))
			{
				while ($sEntry = readdir($rDir))
				{
					if ($sEntry == '.' || $sEntry == '..')
						continue;

					$sEntry = $sCurrentDir . '/' . $sEntry;

					if (is_dir($sEntry))
					{
						$sDirToScan[] = $sEntry;
					}
					else
					{
						if(!$bOnlyOld)
						{
							if(!unlink($sEntry))
								throw new Rapide_Cache_Exception('Cannot delete '.$sEntry);
						}
						else
						{
							if((time() - @filemtime($sEntry) > $this->_iLifeTime))
							{
								if(!unlink($sEntry))
									throw new Rapide_Cache_Exception('Cannot delete '.$sEntry);
							}
						}
					}
				}

				closedir($rDir);
			}

		}

		foreach($aDirArray as $sDirName)
		{
			if($sDirName != realpath($this->_sPath) && $bOnlyOld == false)
			{
				if(!rmdir($sDirName))
				 throw new Rapide_Cache_Exception('Cannot delete ' . $sDirName);
			}
		}

	}
}

?>